#include "type/Type.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include <memory>
#include <string>

UniAST::Type::Type(std::string name) : name(name) {};

std::string UniAST::Type::getName()
{
    return this->name;
}

mlir::Type UniAST::Type::getmlirType(mlir::OpBuilder &builder)
{
    return mlir::Type();
}

UniAST::IntegerType::IntegerType(std::string name, int size)
    : Type(name), size(size)
{
}

mlir::Type UniAST::IntegerType::getmlirType(mlir::OpBuilder &builder)
{
    return builder.getIntegerType(this->size);
}

std::shared_ptr<UniAST::IntegerType> UniAST::IntegerType::get(int size)
{
    std::string name = "int";
    name += std::to_string(size);
    return std::make_shared<IntegerType>(name, size);
}

UniAST::FloatType::FloatType(std::string name, int size)
    : Type(name), size(size)
{
}

mlir::Type UniAST::FloatType::getmlirType(mlir::OpBuilder &builder)
{
    if (this->size == 32)
    {
        return builder.getF32Type();
    }
    else
    {
        return builder.getF64Type();
    }
}

std::shared_ptr<UniAST::FloatType> UniAST::FloatType::get(int size)
{
    std::string name = "float";
    name += std::to_string(size);
    return std::make_shared<FloatType>(name, size);
}

bool UniAST::Type::isIntegerType()
{
    return dynamic_cast<UniAST::IntegerType *>(this) != nullptr;
}

bool UniAST::Type::isFloatType()
{
    return dynamic_cast<UniAST::FloatType *>(this) != nullptr;
}